import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

class DGraph
{
	private Graphics g;
	private DSmallFont font;
	
	private Image bb_img;
	private Graphics bb_g;
	
	private int lastClipX = 0;
	private int lastClipY = 0;
	private int lastClipW = 0;
	private int lastClipH = 0;
	
	private int savedClipX = 0;
	private int savedClipY = 0;
	private int savedClipW = 0;
	private int savedClipH = 0;
	
	private int lastColor = 0;
	
	private int scr_w = 0;
	private int scr_h = 0;
	
	public boolean useBackBuffer = false;
	
	public static final int FONT_SMALL = 1;
	public static final int FONT_BIG = 2;
		
	public DGraph(Graphics _g, int s_w, int s_h, boolean _bb)
	{
		g = _g;
		scr_w = s_w;
		scr_h = s_h;
		setClip(0, 0, scr_w, scr_h);
		
		useBackBuffer = _bb;
		
		if(useBackBuffer)
		{
			bb_img = Image.createImage(scr_w, scr_h);
			bb_g = bb_img.getGraphics();
		
			font = new DSmallFont(bb_g, scr_h);
		}
		else
		{
			font = new DSmallFont(g, scr_h);
		}
	}
	
	void setGraphics(Graphics _g)
	{
		g = _g;
	}
	
	Graphics getFgGraphics()
	{
		return g;
	}
	
	Graphics getBackBufferGraphics()
	{
		return bb_g;
	}
	
	Image getBackBufferImage()
	{
		return bb_img;
	}
	
	void drawRegion(Image srcImg, int x_src, int y_src, int w, int h, int transform, int x_dest, int y_dest, int anchor)
	{
		if(!useBackBuffer)
			g.drawRegion(srcImg, x_src, y_src, w, h, transform, x_dest, y_dest, anchor);
		else
			bb_g.drawRegion(srcImg, x_src, y_src, w, h, transform, x_dest, y_dest, anchor);
	}
	
	void drawImage(Image srcImg, int x, int y, int anchor)
	{
		if(!useBackBuffer)
			g.drawImage(srcImg, x, y, anchor);
		else
			bb_g.drawImage(srcImg, x, y, anchor);
	}
	
	void setColor(int color)
	{
		if(!useBackBuffer)
			g.setColor(color);
		else
			bb_g.setColor(color);
			
		lastColor = color;
	}
	
	int getColor()
	{
		return lastColor;
	}
	
	void setClip(int x, int y, int w, int h)
	{
		if(!useBackBuffer)
			g.setClip(x, y, w, h);
		else
			bb_g.setClip(x, y, w, h);
			
		lastClipX = x;
		lastClipY = y;
		lastClipW = w;
		lastClipH = h;
	}
	
	void saveClip()
	{
		savedClipX = lastClipX;
		savedClipY = lastClipY;
		savedClipW = lastClipW;
		savedClipH = lastClipH;
	}
	
	void restoreClip()
	{
		if(!useBackBuffer)
			g.setClip(savedClipX, savedClipY, savedClipW, savedClipH);
		else
			bb_g.setClip(savedClipX, savedClipY, savedClipW, savedClipH);
	}
	
	int getClipX()
	{
		return lastClipX;
	}
	
	int getClipY()
	{
		return lastClipY;
	}
	
	int getClipW()
	{
		return lastClipW;
	}
	
	int getClipH()
	{
		return lastClipH;
	}
	
	void drawRect(int x, int y, int w, int h)
	{
		if(!useBackBuffer)
			g.drawRect(x, y, w, h);
		else
			bb_g.drawRect(x, y, w, h);
	}
	
	void fillRect(int x, int y, int w, int h)
	{
		if(!useBackBuffer)
			g.fillRect(x, y, w, h);
		else
			bb_g.fillRect(x, y, w, h);
	}
	
	void drawLine(int x1, int y1, int x2, int y2)
	{
		if(!useBackBuffer)
			g.drawLine(x1, y1, x2, y2);
		else
			bb_g.drawLine(x1, y1, x2, y2);
	}
	
	void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
	{
		if(!useBackBuffer)
			g.drawArc(x, y, width, height, startAngle, arcAngle);
		else
			bb_g.drawArc(x, y, width, height, startAngle, arcAngle);
	}
	
	void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)
	{
		if(!useBackBuffer)
			g.fillArc(x, y, width, height, startAngle, arcAngle);
		else
			bb_g.fillArc(x, y, width, height, startAngle, arcAngle);
	}
	
	void drawRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height, boolean processAlpha)
	{
		if(!useBackBuffer)
			g.drawRGB(rgbData, offset, scanlength, x, y, width, height, processAlpha);
		else
			bb_g.drawRGB(rgbData, offset, scanlength, x, y, width, height, processAlpha);
	}
	
	void paintBuffer()
	{
		if(useBackBuffer)
			g.drawImage(bb_img, 0, 0, 0);
			
	}
	
	private int alphaBlend(int fgPixel, int bgPixel, int alphaLevel)
	{
		return (((fgPixel * 0xFF) + (bgPixel * (0xFF - alphaLevel))) / 0xFF);
	}
	
	void fillRoundRect(int x, int y, int w, int h, int arcH, int arcW)
	{
		int lastY = 0;
	
		for(int i = arcH; i > 0; i--)
		{
			fillRect(x + (arcW / (arcH - i + 1)), y + (arcH - i), w - (arcW / (arcH - i + 1)) * 2, 1);
			lastY = y + (arcH - i);
		}
		
		lastY++;
		
		fillRect(x, lastY, w, h - arcH * 2);
		
		lastY--;
				
		for(int j = 0; j < arcH + 1; j++)
		{
			fillRect(x + (arcW / (arcH - j + 1)), lastY + h - arcH * 2 + j, w - (arcW / (arcH - j + 1)) * 2, 1);
		}
	}
	
	void drawRoundButton(int x, int y, int w, int h, int startColor, int endColor)
	{
		drawRoundButton("", x, y, w, h, startColor, endColor, 0x000000);
	}
	
	void drawRoundButton(String str, int x, int y, int w, int h, int startColor, int endColor, int fontColor)
	{
		int rs = startColor >>>	16;
		int gs = (startColor >>> 8) & 0x000000FF;
		int bs = startColor & 0x000000FF;
				
		int rRatio = ((rs - (endColor >>> 16)) / (h / 4)) * -1;
		int gRatio = ((gs - ((endColor >>> 8) & 0x000000FF)) / (h / 4)) * -1;
		int bRatio = ((bs - (endColor & 0x000000FF)) / (h / 4)) * -1;
		
		for(int i = 0; i < h / 4; i++)
		{
			g.setColor((rs<<16) | (gs<<8) | (bs));
			rs+=rRatio;
			gs+=gRatio;
			bs+=bRatio;
			
			fillRoundRect(x + i, y + i, w - i * 2, h - i * 2, h * 10 / 100, w * 10 / 100);
		}
		
		setFontColor(fontColor);
		
		if(getStringWidth(str) < w)
		{
			drawString(str, x + w / 2, y + h / 2 + getFontHeight() / 2,DSmallFont.BOTTOM | DSmallFont.HCENTER);
		}
		else
		{
			String[] buffer = str.split(" ");
			int lines = buffer.length;
			int lastIndex = 0;
			
			for(int k = 0; k < buffer.length - 1; k++)
			{
				if(getStringWidth(buffer[lastIndex] + " " + buffer[k + 1]) < w)
				{
					buffer[lastIndex] = buffer[lastIndex] + " " + buffer[k + 1];
					lines--;
				}
				else
				{
					lastIndex++;
					buffer[lastIndex] = buffer[k + 1];
				}
			}
			
			for(int j = 0; j < lines; j++)
			{
				drawString(buffer[j], x + w / 2, y + (h / (lines+1)) + (h / (lines+1)) * j + getFontHeight() / 2, DSmallFont.BOTTOM | DSmallFont.HCENTER);
			}
		}
	}
	
	void drawGFRect(int x, int y, int w, int h, int startColor, int endColor)
	{	
		int rs = startColor >>>	16;
		int gs = (startColor >>> 8) & 0x000000FF;
		int bs = startColor & 0x000000FF;
				
		int rRatio = ((rs - (endColor >>> 16)) / (h)) * -1;
		int gRatio = ((gs - ((endColor >>> 8) & 0x000000FF)) / (h)) * -1;
		int bRatio = ((bs - (endColor & 0x000000FF)) / (h)) * -1;
				
		for(int i = 0; i < h; i++)
		{
			setColor((rs<<16) | (gs<<8) | (bs));
			fillRect(x, y + i, w, 1);
			rs+=rRatio;
			gs+=gRatio;
			bs+=bRatio;
		}		
	}
	
	void drawAlphaRect(int x, int y, int w, int h, int alphaLevel)
	{
		int[] rect = new int[w * h];
		
		for(int i = 0; i < rect.length; i++)
		{
			rect[i] = (alphaLevel << 24) | getColor();
		}
		
		drawRGB(rect, 0, w, x, y, w, h, true);
	}
	
	void setFont(int type)
	{
		font.pixelSize = type;
	}
		
	void drawString(String str, int x, int y, int anchor)
	{
		font.drawString(str, x, y, anchor);
	}
	
	void drawString(String str, int x, int y, int maxWidth, int anchor)
	{
		font.drawString(str, x, y, maxWidth, anchor);
	}
	
	int getFontPixelSize()
	{
		return font.pixelSize;
	}
	
	int getStringWidth(String str)
	{
		return font.getStringWidth(str);
	}
	
	int getFontHeight()
	{
		return font.getFontHeight();
	}
	
	void setFontColor(int color)
	{
		font.setColor(color);
	}
	
	void setFontHLColor(int color)
	{
		font.hlColor = color;
	}
	
	int getFontWidth()
	{
		return font.getFontWidth();
	}
}